Préparation de l'espace de travail (définition du chemin des packages) :


In [1]:
%matplotlib inline
import sys
sys.path.append(r'C:\Users\ntotaro\Documents\TOOLBOX\PYTHON')
import numpy as np #import des fonctions mathématiques du package numpy

Notice d'utilisation des objets "cartesianLine", "lineGridPoints2D" et "lineGridPoints3D"

Les objets "cartesianLine" permette de faire des traitements (bruit, transformée de Fourier spatiale, zero-padding, affichage) sur des données d'une ligne régulière. Les objets "lineGridPoints2D" et "lineGridPoints3D" héritent de l'objet "cartesianLine". Ils permettent de repérer la ligne régulière dans un espace 2D ou 3D

cartesianLine

Pour utiliser cet objet il faut déjà l'importer


In [2]:
from SiRoCo_Project.tools.classCartesianLine import cartesianLine

Ensuite, il faut initialiser un objet "cartesianLine"


In [3]:
ligne1 = cartesianLine()

A ce niveau là, l'objet "ligne1" est vide (pas de coordonées, pas de données). On peut associer des points et des données de plusieurs manières différentes : soit d'un seul bloc soit par ajouts successifs.

Ajout de données d'un seul bloc

Soit des données disponible sous la forme de listes ou de vecteur (numpy array). Ces données peuvent être ajoutées directement à l'objet cartesianLine d'un seul bloc du moment qu'elles sont de mêmes dimension (points et valeurs). Prenons par exemple les données suivantes, associées à une liste de points:


In [4]:
x = np.linspace(0.0,1.0,100) # liste de 20 valeurs de x entre 0. et 1. 
print("valeurs de x : " + str(x))
v = np.sin(2*np.pi/0.6*x)
print("valeurs de la fonction : "+str(v))


valeurs de x : [ 0.          0.01010101  0.02020202  0.03030303  0.04040404  0.05050505
  0.06060606  0.07070707  0.08080808  0.09090909  0.1010101   0.11111111
  0.12121212  0.13131313  0.14141414  0.15151515  0.16161616  0.17171717
  0.18181818  0.19191919  0.2020202   0.21212121  0.22222222  0.23232323
  0.24242424  0.25252525  0.26262626  0.27272727  0.28282828  0.29292929
  0.3030303   0.31313131  0.32323232  0.33333333  0.34343434  0.35353535
  0.36363636  0.37373737  0.38383838  0.39393939  0.4040404   0.41414141
  0.42424242  0.43434343  0.44444444  0.45454545  0.46464646  0.47474747
  0.48484848  0.49494949  0.50505051  0.51515152  0.52525253  0.53535354
  0.54545455  0.55555556  0.56565657  0.57575758  0.58585859  0.5959596
  0.60606061  0.61616162  0.62626263  0.63636364  0.64646465  0.65656566
  0.66666667  0.67676768  0.68686869  0.6969697   0.70707071  0.71717172
  0.72727273  0.73737374  0.74747475  0.75757576  0.76767677  0.77777778
  0.78787879  0.7979798   0.80808081  0.81818182  0.82828283  0.83838384
  0.84848485  0.85858586  0.86868687  0.87878788  0.88888889  0.8989899
  0.90909091  0.91919192  0.92929293  0.93939394  0.94949495  0.95959596
  0.96969697  0.97979798  0.98989899  1.        ]
valeurs de la fonction : [ 0.          0.10558039  0.20998054  0.31203345  0.41059829  0.50457329
  0.59290793  0.67461478  0.74878047  0.81457595  0.87126573  0.91821611
  0.95490224  0.98091404  0.99596074  0.99987413  0.99261047  0.97425095
  0.94500082  0.90518703  0.85525465  0.79576184  0.72737364  0.65085453
  0.56705986  0.47692635  0.38146153  0.28173256  0.17885425  0.07397663
 -0.03172793 -0.13707783 -0.24089541 -0.34202014 -0.43932162 -0.53171217
 -0.61815899 -0.69769574 -0.76943334 -0.83256985 -0.88639953 -0.93032062
 -0.96384216 -0.98658943 -0.99830816 -0.99886734 -0.98826072 -0.96660688
 -0.93414786 -0.89124651 -0.8383824  -0.77614646 -0.70523441 -0.62643892
 -0.54064082 -0.44879918 -0.35194066 -0.25114799 -0.14754787 -0.04229839
  0.06342392  0.16843725  0.27156771  0.37166246  0.46760259  0.55831566
  0.64278761  0.72007419  0.78931145  0.84972543  0.90064079  0.94148837
  0.97181157  0.99127141  0.99965037  0.99685478  0.98291589  0.95798951
  0.92235429  0.87640858  0.82066597  0.75574957  0.68238507  0.60139255
  0.51367739  0.42022011  0.32206542  0.22031053  0.11609291  0.01057756
 -0.09505604 -0.19962706 -0.30196656 -0.40093054 -0.49541273 -0.58435697
 -0.666769   -0.74172758 -0.8083948  -0.8660254 ]

L'ensemble des données étant créé, on peut maintenant les affecter à l'objet "ligne1" :


In [5]:
ligne1.setX(x)
ligne1.setData(v)
print(ligne1.data1.shape)


(100L,)

Ajouts des données successifs

Une autre possibilité pour l'ajout de données est de le faire de manière successive dans une boucle par exemple. L'exemple suivant présente cette possibilité :


In [6]:
#ligne1.delete() # efface les données précédemment affectées
x = np.linspace(0.0,1.0,100)
#for valx in x:
#    valv = np.sin(2*np.pi/0.6*valx)
#    ligne1.append(valx, valv)
#print(ligne1.data1.shape)

Dernière variante, il est possible d'affecter les points et les valeurs successivement mais séparément. Dans l'exemple suivant, les points sont affectés d'un bloc mais les données successivement :


In [7]:
#ligne1.delete() # efface les données précédemment affectées
x = np.linspace(0.0,1.0,100)
#ligne1.setX(x)
#for valx in x:
#    valv = np.sin(2*np.pi/0.6*valx)
#    ligne1.appendDataOnly(valv)

La même chose est possible (affecter successivement uniquement les points) à l'aide de la méthode appendXOnly

Méthodes disponibles dans les objets de type cartesianLine

Affichage des données (méthode plot)

L'affichage des données contenues dans l'objet se fait simplement en appelant la méthode plot:


In [8]:
ligne1.plot()


Par la suite, cette fonction sera systématiquement utilisée pour illustrer les fonctions.

Ajout de bruit (méthode noisify)

L'ajout de bruit de mesure d'un certain SNR (Signal to Noise Ratio) se fait comme suit:


In [9]:
ligne1.noisify(SNR = 20) #ajout d'un bruit d'un SNR de 20dB (sur la partie réelle et sur la partie imaginaire)
ligne1.plot() #la fonction plot n'affiche qu'une seule courbe si les données sont réelles, 2 si elles sont complexes


Fenêtrage (méthode windowing)

Des fenêtrages des donées sont possibles. Pour l'instant les fenêtres "rectangular" et "hanning" sont disponibles. Le fenêtrage de type "hanning" se fait sur toute la fenêtre (quelles que soient les valeurs de x). Le filtrage 'rectangular' applique un filtre passe-bande (0 ou 1) entre les valeurs -cuttingv et +cuttingv (valeur de coupure)


In [10]:
ligne1.windowing(wtype = 'hanning')# applique une fenêtre de type hanning aux données
#ligne1.windowing(wtype = 'rectangular', cuttingv = 0.6)# applique un filtre passe-bande entre -0.6 et +0.6
ligne1.plot()


Ajout d'un zero-padding (méthode padding)

L'ajout de zéros avant et après les valeurs (zéro-padding) se contrôle avec la méthode padding qui prend un paramètre 'coeff'. Ce coefficient indique que coeff x nbpoints_x seront ajoutés avant et après les données. Par exemple :


In [11]:
ligne1.padding(coeff = 1)# ajoute autant de 0 avant et après les données qui n'y avait de valeurs de données
ligne1.plot()


Passage dans le domaine des nombres d'onde et inverse (méthode kspace et kspace_inverse)

On peut passer dans le domaine des nombres d'ondes et faire la transformation inverse en utilisant les méthodes kspace et kspace_inverse. Les valeurs de x sont modifiées en valeurs de kx.


In [12]:
ligne1.kspace()
ligne1.plot()



In [13]:
ligne1.kspace_inverse()
ligne1.plot()


Annulation de tous les traitements appliqués (méthode resetProcessing)

Le retour aux données initialement affectées à l'objet se fait par :


In [14]:
ligne1.resetProcessing()
ligne1.plot()
print(ligne1.data1.shape)


(100L,)

Algèbre entre objets de type cartesianLine

Les objets de types cartesianLine peuvent s'ajouter, se soustraire, se multiplier, se diviser entre eux pourvu qu'ils soient de mêmes dimensions. Le résultat de ce calcul est de type cartesianLine (évidemment, toutes les méthodes sont héritées). Par exemple, créons un nouvel objet "ligne2" :


In [15]:
v2 = np.cos(2*np.pi/0.6*x)
ligne2 = cartesianLine()
ligne2.setX(x)
ligne2.setData(v2)
ligne2.plot()


On peut additionner les deux objets :


In [16]:
somme = ligne1 + ligne2
somme.plot()


les soustraire :


In [17]:
reste = ligne1 - ligne2
reste.plot()


les multiplier :


In [18]:
mult = ligne1 * ligne2
mult.plot()


et les diviser :


In [19]:
divi = ligne1 / ligne2 # attention à la division par 0
divi.plot()


et faire une combinaison de tout ça


In [20]:
calc = ligne1*2 + ligne2/5 * ligne1
calc.plot()


Accès aux données

Il est possible d'accéder aux données contenues dans les objets cartesianLine en utilisant les méthodes getX et getData comme suit :


In [21]:
vectx = calc.getX()
val = calc.getData()

Ces données sont des numpy arrays. On peut récupérer d'autres informations comme le type de données (scalaire ou vectorielle, méthode getDataType), l'espace des données (géométrique ou espace des nombres d'ondes, méthode getDataSpace) la longueur de la ligne (méthode length) :


In [22]:
t = ligne1.getDataType() # renvoie "scalar" ou "vector"
s = ligne1.getDataSpace() # renvoie "space" ou "kspace"
longueur = ligne1.length() 
print(t)
print(s)
print(longueur)


scalar
space
100

Cas des données vectorielles

Toutes les méthodes et calculs algébriques présentés ci-dessus pour le cas de données scalaires sont accessibles dans le cas de données vectorielles. La principale différence réside dans l'initialisation de l'objet:


In [23]:
vx = np.cos(3*x)
vy = np.cos(2*x)
vz = np.sin(3*x)
# Premiere methode -> d'un bloc
lignevect1 = cartesianLine(dataType='vector')
lignevect1.setX(x)
lignevect1.setData([vx, vy, vz]) #les données peuvent être une liste de 3 vecteurs ou une matrice (np.array)

# Deuxième méthode -> à l'initialisation
lignevect2 = cartesianLine(dataType='vector', x = x, datax = vx, datay = vy, dataz = vz)

# Troisième méthode -> au fur et à mesure
lignevect3 = cartesianLine(dataType='vector')
for nn, xx in enumerate(x):
    lignevect3.append(xx, [vx[nn], vy[nn], vz[nn]])
    # ou
    # lignevect3.appendXOnly(xx)
    # lignevect3.appendDataOnly([vx[nn], vy[nn], vz[nn]])
    
lignevect1.plot()


lineGridPoints2D et lineGridPoints3D

Ces deux objets, très similaires, héritent tous les deux de toutes les méthodes précédemment exposées pour les object cartesianLine. Ces objets représentent des lignes de points régulièrement espacés dans l'espace 2D ou 3D. Les classes lineGridPoints2D et lineGridPoints3D s'importe par :


In [24]:
from SiRoCo_Project.tools.classCartesianLine import lineGridPoints2D, lineGridPoints3D

On déclare ensuite des objets (ici une ligne l2d et une ligne l3d)


In [25]:
l2d = lineGridPoints2D(x0=0.1, y0=0.2, L=1., d=0.01, theta=0., dataType='scalar') #création d'une ligne de points associée à des données scalaires dont le point initial est en (x0,y0), d'une longueur L, avec des points espacés de d et faisant un angle theta avec l'axe x
l3d = lineGridPoints3D(x0=0.1, y0=0.2, z0=0.1, L=1., d=0.01, theta=0., phi=0., dataType='vector') #création d'une ligne de points associée à des données vectorielles dont le point initial est en (x0,y0,z0), d'une longueur L, avec des points espacés de d et faisant un angle theta avec l'axe x et un angle phi

On peut ensuite associer des données aux points dont les coordonnées ont été calculées dans le repère 2D ou 3D (contrairement aux cartesianLine on ne doit pas affecter de valeurs de x, elles sont calculées en fonction des paramètres entrés). Les données peuvent être affectées par les méthodes (appendDataOnly) ou (setData) !!les données doivent être compatibles avec le nombre de points définis!!.

Exemple lineGridPoints2D : Prenons l'exemple d'une plaque appuyée de dimension Lx et Lz. On souhait récupérer la déformée modale du mode (m=3, n=2) sur une ligne suivant la diagonale de la plaque. L'exemple suivant résoud ce problème


In [26]:
m=3
n=2
Lx, Ly = 0.7, 1.
modeLine = lineGridPoints2D(x0=0., y0=0., L=np.sqrt(Lx**2+Ly**2), d=0.01, theta=np.arctan(Lx/Ly), dataType='scalar') 
for xc, yc in zip(modeLine.getX2D(), modeLine.getY2D()):
    defmn = np.sin(m*np.pi/Lx*xc)*np.sin(n*np.pi/Ly*yc)
    modeLine.appendDataOnly(defmn)

modeLine.setXLabel('Position sur la diagonale (m)')
modeLine.setDataLabel('Mode (' + str(m) + ',' + str(n) + ')')
modeLine.plot()


Exemple lineGridPoints3D : Soit une cavité de dimensions Lx, Ly, Lz. On souhaite tracer le mode (4,5,2) suivant une ligne parralèlle à z et démarrant au point (0.2,0.3,0.)


In [27]:
m = 4
n = 5
p = 2
Lx, Ly, Lz = 0.7, 1., 1.2
modeLine2 = lineGridPoints3D(x0=0.2, y0=0.3, z0=0., L=Lz, d=0.01, theta=0, phi=-np.pi/2, dataType='scalar') 
for xc, yc, zc in zip(modeLine2.getX3D(), modeLine2.getY3D(), modeLine2.getZ3D()):
    defmnp = np.cos(m*np.pi/Lx*xc)*np.cos(n*np.pi/Ly*yc)*np.cos(p*np.pi/Lz*zc)
    modeLine2.appendDataOnly(defmnp)

modeLine2.setXLabel('Position selon z (m)')
modeLine2.setDataLabel('Mode (' + str(m) + ',' + str(n) + ',' + str(p) + ')')
modeLine2.plot()